package com.concurrent.sample.business.service.impl;

import com.concurrent.sample.business.entity.PositionEntity;
import com.concurrent.sample.business.service.PositionService;
import com.concurrent.sample.business.dto.debug.AppDebugInfoDTO;
import com.concurrent.sample.business.dto.debug.DataMemoryTypeEnum;
import com.concurrent.sample.business.dto.param.PositionUpdateQtyParam;
import com.concurrent.sample.business.repo.PositionRepo;
import com.concurrent.sample.common.util.LongUtil;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import javax.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Slf4j
public class PositionServiceImpl implements PositionService {

  public static Map<Long, PositionEntity> ID_CONTAINER;

  private static AtomicLong idAtomic = new AtomicLong(0);

  private final PositionRepo positionRepo;

  @PostConstruct
  public void init(){
    List<PositionEntity> list = positionRepo.findAll();
    ID_CONTAINER = new ConcurrentHashMap<>();
    for(PositionEntity positionEntity : list){
      ID_CONTAINER.put(positionEntity.getId(), positionEntity);
    }
  }

  @Transactional(rollbackFor = Exception.class)
  @Override
  public PositionEntity updateQty(PositionUpdateQtyParam positionParam) {
    PositionEntity position;

    if(AppDebugInfoDTO.dataMemoryType == DataMemoryTypeEnum.LOCAL){
      position = ID_CONTAINER.get(positionParam.getPositionId());
    } else {
      position = positionRepo.findById(positionParam.getPositionId()).get();
    }

    log.info("position minus. positionId = {}, version = {}, " +
            "src(availableSaleQty = {}, leaveShortQty = {}) " +
            "update(availableSaleQty = {}, leaveShortQty = {}))",
        position.getId(), position.getVersion(),
        position.getAvailableSaleQty(), position.getLeaveShortQty(),
        positionParam.getAvailableSaleQty(), positionParam.getLeaveShortQty()
    );

    position.setAvailableSaleQty(
            LongUtil.minusByNullToZero(position.getAvailableSaleQty(), positionParam.getAvailableSaleQty()))
        .setAvailableBuyQty(LongUtil.minusByNullToZero(position.getAvailableBuyQty(), positionParam.getAvailableBuyQty()))
        .setIntradaySoldQty(LongUtil.minusByNullToZero(position.getIntradaySoldQty(), positionParam.getIntradaySoldQty()))
        .setIntradayBuyQty(LongUtil.minusByNullToZero(position.getIntradayBuyQty(), positionParam.getIntradayBuyQty()))
        .setLeaveLoanQty(LongUtil.minusByNullToZero(position.getLeaveLoanQty(), positionParam.getLeaveLoanQty()))
        .setLeaveShortQty(LongUtil.minusByNullToZero(position.getLeaveShortQty(), positionParam.getLeaveShortQty()))
        .setReturnableQty(LongUtil.minusByNullToZero(position.getReturnableQty(), positionParam.getReturnableQty()))
    ;

    if(AppDebugInfoDTO.dataMemoryType == DataMemoryTypeEnum.LOCAL){
      position.setVersion(position.getVersion() + 1);
      ID_CONTAINER.put(positionParam.getPositionId(), position);
    }

    return position;
  }

}
